package org.bee.controller;

import org.bee.ResultTool;
import org.bee.json.JsonUtils;
import org.bee.model.queue.NoticeMessage;
import org.bee.model.result.Result;
import org.bee.secuirty.annotation.ApiAuth;
import org.bee.secuirty.annotation.TokenIgnore;
import org.bee.secuirty.context.CurrentUser;
import org.bee.secuirty.model.UserInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 消息通知控制器
 */
@RestController
@RequestMapping("/sse")
public class NoticeController {
    private final Map<String, SseEmitter> emitters = new ConcurrentHashMap<>();

    @Value("${sse.timeout}")
    private Long timeout;

    /**
     * 消息通知sse接口
     *
     * @return sse对象
     */
    @ApiAuth(value = "sse.notice", description = "消息通知")
    @GetMapping(value = "/notice", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter sse() {
        UserInfo user = CurrentUser.getUser();
        String key = user.getToken();
        SseEmitter sseEmitter = new SseEmitter(timeout);
        sseEmitter.onCompletion(() -> {
            System.out.println("completion");
            emitters.remove(key);
            System.out.println(emitters.size());
        });
        sseEmitter.onError((_) -> {
            System.out.println("error");
            emitters.remove(key);
            System.out.println(emitters.size());
        });
        sseEmitter.onTimeout(() -> {
            System.out.println("timeout");
            emitters.remove(key);
            System.out.println(emitters.size());
        });
        try {
            sseEmitter.send("");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        emitters.put(key, sseEmitter);
        return sseEmitter;
    }

    @TokenIgnore
    @DeleteMapping("/delete")
    public Result delete() {
        Result result = ResultTool.success();
        UserInfo user = CurrentUser.getUser();
        if (null != user) {
            String key = user.getToken();
            emitters.remove(key);
        }
        return result;
    }

    public void send(String data) {
        NoticeMessage noticeMessage = JsonUtils.fromJson(data, NoticeMessage.class);
        if (null == noticeMessage) {
            return;
        }
        if (null != noticeMessage.getTokens() && !noticeMessage.getTokens().isEmpty()) {
            List<String> tokens = noticeMessage.getTokens();
            tokens.forEach(token -> {
                SseEmitter emitter = emitters.get(token);
                if (null != emitter) {
                    try {
                        emitter.send(data);
                    } catch (IOException e) {
                        System.out.println("发送消息失败"+e.getMessage());
                        emitter.complete();
                    }
                }
            });
        } else {
            emitters.forEach((_, v) -> {
                try {
                    v.send(data);
                } catch (IOException e) {
                    System.out.println("发送消息失败"+e.getMessage());
                    v.complete();
                }
            });
        }
    }

}
